#include "Camera.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <QQuaternion>
#include <cmath>
#include <QDebug>

Camera::Camera()
  : mEye(0,0,0), mCenter(0,0,0), mUp(0,1,0)
{}

Camera::Camera(const QVector3D &eye, const QVector3D &center, const QVector3D &up)
  : mEye(eye), mCenter(center), mUp(up)
{}

void Camera::look() const
{
  gluLookAt(mEye.x(), mEye.y(), mEye.z(),
            mCenter.x(), mCenter.y(), mCenter.z(),
            mUp.x(), mUp.y(), mUp.z());
}

float Camera::distance() const
{
  return (mEye - mCenter).length();
}

const QVector3D& Camera::center() const
{
  return mCenter;
}

const QVector3D& Camera::eye() const
{
  return mEye;
}

void Camera::setEye(const QVector3D &eye)
{
  mEye = eye;
}

void Camera::setCenter(const QVector3D &center)
{
  mCenter = center;
}

void Camera::move(float xoffset, float yoffset, float zoffset)
{
  mEye.setX(mEye.x()+xoffset);
  mEye.setY(mEye.y()+yoffset);
  mEye.setZ(mEye.z()+zoffset);

  mCenter.setX(mCenter.x()+xoffset);
  mCenter.setY(mCenter.y()+yoffset);
  mCenter.setZ(mCenter.z()+zoffset);
}

void Camera::pan(float angle)
{
  angle *= M_PI/180.0;
  QVector3D normal((mEye-mCenter).normalized());

}

void Camera::tilt(float angle)
{
  angle *= M_PI/180.0;
  QVector3D dir((mEye-mCenter).normalized());
  float r = (mEye-mCenter).length();
  float theta = acos(QVector3D::dotProduct(dir, QVector3D(0,0,1))/dir.length()),
        phi = acos(QVector3D::dotProduct(dir, QVector3D(1,0,0))/dir.length());

  theta += angle;

  float x(r*sin(theta)*cos(phi)),
        y(r*sin(theta)*sin(phi)),
        z(r*cos(theta));
  mEye.setX(x);
  mEye.setY(y);
  mEye.setZ(z);
}

void Camera::spin(float angle)
{
  angle *= M_PI/180.0;
  float x(mEye.x()*cos(angle) - mEye.y()*sin(angle)),
        y(mEye.x()*sin(angle) + mEye.y()*cos(angle));

  mEye.setX(x);
  mEye.setY(y);
}

void Camera::zoom(float distance)
{
  QVector3D dir((mEye-mCenter).normalized());
  mEye = mCenter + dir * distance;
}
